package com.fg.generaltor;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fg.entity.GeneralTable;
import com.fg.mapper.GeneralTableMapper;
import com.fg.service.GeneralTableService;
import com.fg.utils.ToolsThreadContext;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;

/**
 * @author: 王富贵
 * @description: 基础sql生成器，相关实现需要注入bean
 * @createTime: 2024年04月20日 23:21:47
 */
@Slf4j
public abstract class BaseGenerator {

    /**
     * sql生成使用的行数,默认60
     * 例如生成update场景下个sql只更新60条，循环生成sql语句，避免打爆线上库或者超时等问题
     */
    @Getter
    @Setter
    protected Integer batchCount = 60;

    @Resource
    protected GeneralTableMapper generalTableMapper;
    @Resource
    public GeneralTableService generalTableService;

    @PostConstruct
    public void generate() {
        // 前置动作
        setTableName();

        // 执行流程
        process();

        // 后置动作
        ToolsThreadContext.remove();
    }

    /**
     * 执行流程
     */
    abstract public void process();

    /**
     * 设置表名
     */
    void setTableName() {
        setTableName("general_table");
    }

    /**
     * 设置表名
     */
    protected void setTableName(String tableName) {
        ToolsThreadContext.get().setDynamicTableName("`" + tableName + "`");
    }

    /**
     * 设置输出文件名称
     *
     * @param fileName
     */
    protected void setOutPutFileName(String fileName) {
        ToolsThreadContext.get().setOutputFileName(fileName);
    }

    /**
     * 设置输出文件名称
     *
     * @param filePatch
     * @param fileName
     */
    protected void setOutPutFileName(String filePatch, String fileName) {
        ToolsThreadContext.get().setOutputFileName(fileName);
        ToolsThreadContext.get().setOutputFilePatch(filePatch);
    }

    /**
     * 生成批量update语句
     *
     * @param generalMapsLists 传入的表数据
     * @param open             外层条件,可以写set和最外层where。可以获取到wrapper和拆封过后的list<map>
     * @param forEach          遍历条件,可以用or去包围。可以获取到wrapper和拆封过后的每一条map
     */
    protected void batchUpdate(List<Map<String, String>> generalMapsLists,
                               BiConsumer<UpdateWrapper<GeneralTable>, List<Map<String, String>>> open,
                               BiConsumer<UpdateWrapper<GeneralTable>, Map<String, String>> forEach) {
        batchUpdate(generalMapsLists, open, forEach, null);
    }

    /**
     * 生成批量update语句
     *
     * @param generalMapsLists 传入的表数据
     * @param open             外层条件,可以写set和最外层where。可以获取到wrapper和拆封过后的list<map>
     * @param forEach          遍历条件,可以用or去包围。可以获取到wrapper和拆封过后的每一条map
     * @param last             最后执行条件
     */
    protected void batchUpdate(List<Map<String, String>> generalMapsLists,
                               BiConsumer<UpdateWrapper<GeneralTable>, List<Map<String, String>>> open,
                               BiConsumer<UpdateWrapper<GeneralTable>, Map<String, String>> forEach,
                               BiConsumer<UpdateWrapper<GeneralTable>, List<Map<String, String>>> last) {
        UpdateWrapper<GeneralTable> updateWrapper = new UpdateWrapper<>();
        // 拆分每次更新batchCount(默认60)条数据
        for (List<Map<String, String>> generalMapLists : Lists.partition(generalMapsLists, batchCount)) {
            // 外层条件
            if (Objects.nonNull(open)) {
                open.accept(updateWrapper, generalMapLists);
            }
            // 遍历条件
            if (Objects.nonNull(forEach)) {
                updateWrapper.nested(generalTableUpdateWrapper -> {
                    for (Map<String, String> generalMapList : generalMapLists) {
                        forEach.accept(generalTableUpdateWrapper, generalMapList);
                    }
                });
            }
            // 最后条件
            if (Objects.nonNull(last)) {
                last.accept(updateWrapper, generalMapLists);
            }
            generalTableMapper.update(updateWrapper);
            updateWrapper.clear();
        }
    }

    /**
     * 生成批量delete语句
     *
     * @param generalMapsLists 传入的表数据
     * @param open             外层条件,可以写set和最外层where。可以获取到wrapper和拆封过后的list<map>
     * @param forEach          遍历条件,可以用or去包围。可以获取到wrapper和拆封过后的每一条map
     */
    protected void batchDelete(List<Map<String, String>> generalMapsLists,
                               BiConsumer<QueryWrapper<GeneralTable>, List<Map<String, String>>> open,
                               BiConsumer<QueryWrapper<GeneralTable>, Map<String, String>> forEach) {
        batchDelete(generalMapsLists, open, forEach, null);
    }

    /**
     * 生成批量delete语句
     *
     * @param generalMapsLists 传入的表数据
     * @param open             外层条件,可以写set和最外层where。可以获取到wrapper和拆封过后的list<map>
     * @param forEach          遍历条件,可以用or去包围。可以获取到wrapper和拆封过后的每一条map
     * @param last             最后执行条件
     */
    protected void batchDelete(List<Map<String, String>> generalMapsLists,
                               BiConsumer<QueryWrapper<GeneralTable>, List<Map<String, String>>> open,
                               BiConsumer<QueryWrapper<GeneralTable>, Map<String, String>> forEach,
                               BiConsumer<QueryWrapper<GeneralTable>, List<Map<String, String>>> last) {
        QueryWrapper<GeneralTable> queryWrapper = new QueryWrapper<>();
        // 拆分每次更新batchCount(默认60)条数据
        for (List<Map<String, String>> generalMapsList : Lists.partition(generalMapsLists, batchCount)) {
            // 外层条件
            if (Objects.nonNull(open)) {
                open.accept(queryWrapper, generalMapsList);
            }

            // 遍历条件
            if (Objects.nonNull(forEach)) {
                queryWrapper.nested(generalTableQueryWrapper -> {
                    for (Map<String, String> generalMapList : generalMapsList) {
                        forEach.accept(generalTableQueryWrapper, generalMapList);
                    }
                });
            }

            // 最后条件
            if (Objects.nonNull(last)) {
                last.accept(queryWrapper, generalMapsList);
            }
            // 执行sql
            generalTableMapper.delete(queryWrapper);
            queryWrapper.clear();
        }
    }

    /**
     * 生成批量select语句
     *
     * @param generalMapsLists 传入的表数据
     * @param open             外层条件,可以写set和最外层where。可以获取到wrapper和拆封过后的list<map>
     * @param forEach          遍历条件,可以用or去包围。可以获取到wrapper和拆封过后的每一条map
     */
    protected void batchSelect(List<Map<String, String>> generalMapsLists,
                               BiConsumer<QueryWrapper<GeneralTable>, List<Map<String, String>>> open,
                               BiConsumer<QueryWrapper<GeneralTable>, Map<String, String>> forEach) {
        batchSelect(generalMapsLists, open, forEach, null);
    }

    /**
     * 生成批量select语句
     *
     * @param generalMapsLists 传入的表数据
     * @param open             外层条件,可以写set和最外层where。可以获取到wrapper和拆封过后的list<map>
     * @param forEach          遍历条件,可以用or去包围。可以获取到wrapper和拆封过后的每一条map
     * @param last             最后执行条件
     */
    protected void batchSelect(List<Map<String, String>> generalMapsLists,
                               BiConsumer<QueryWrapper<GeneralTable>, List<Map<String, String>>> open,
                               BiConsumer<QueryWrapper<GeneralTable>, Map<String, String>> forEach,
                               BiConsumer<QueryWrapper<GeneralTable>, List<Map<String, String>>> last) {
        QueryWrapper<GeneralTable> queryWrapper = new QueryWrapper<>();
        // 拆分每次更新batchCount(默认60)条数据
        for (List<Map<String, String>> generalMapsList : Lists.partition(generalMapsLists, batchCount)) {
            // 外层条件
            if (Objects.nonNull(open)) {
                open.accept(queryWrapper, generalMapsList);
            }
            // 遍历条件
            if (Objects.nonNull(forEach)) {
                queryWrapper.nested(generalTableQueryWrapper -> {
                    for (Map<String, String> generalMapList : generalMapsList) {
                        forEach.accept(generalTableQueryWrapper, generalMapList);
                    }
                });
            }
            // 最后条件
            if (Objects.nonNull(last)) {
                last.accept(queryWrapper, generalMapsList);
            }
            generalTableMapper.selectObjs(queryWrapper);
            queryWrapper.clear();
        }
    }
}
